#pragma once
#include <iostream>
#include <memory>
#include "es.hpp"
#include "user.hxx"
#include "message.hxx"
#include <boost/date_time/posix_time/posix_time.hpp>
/*
ES数据管理：
在用户注册成功的时候。将用户的元信息，向ES也存储一份，以便于用户的搜索
搜索关键字：是一个字符串，可能是一个用户ID，也可能是一个手机号，也可能是一个昵称的一部分
           且搜索的时候，不能搜索到自己，以及自己的好友，过滤条件起始就是一组用户ID
用户元信息：用户ID，用户昵称，手机号，签名，头像ID
ES的管理操作：
1.创建用户索引
2.新增数据/更新数据
3.搜索用户
*/

namespace zrb
{
    class ESClientFactory
    {
    public:
        static std::shared_ptr<elasticlient::Client> create(std::string& host)
        {
            std::vector<std::string> host_list = {"http://127.0.0.1:9200/"};
            return std::make_shared<elasticlient::Client>(host_list);
        }
    };
    class ESUser
    {
    public:
        using ptr = std::shared_ptr<ESUser>;
        ESUser(std::shared_ptr<elasticlient::Client> client)
            :_client(client)
        {}

        //创建用户索引
        bool createIndex()
        {
            bool ret = ESIndex(_client, "user")
                .append("user_id", "keyword", "standard", true) //keyword: 用于精确匹配的字符串数据。不会进行分词处理
                .append("nickname")
                .append("phone", "keyword", "standard", true)
                .append("description","text", "standard", false)
                .append("avatar_id","text", "standard", false)
                .create();

            if (ret == false)
            {
                LOG_INFO("用户信息索引创建失败!");
                return false;
            }
            else 
            {
                LOG_INFO("用户信息索引创建成功!");
                return true;
            }
        }

        //新增数据/修改数据
        bool appendData(const std::string& user_id,
            const std::string& nickname,
            const std::string& phone,
            const std::string& description,
            const std::string& avatar_id)
        {
            auto ret = ESInsert(_client, "user")
                .append("user_id", user_id)
                .append("nickname", nickname)
                .append("phone",phone)
                .append("description", description)
                .append("avatar_id", avatar_id)
                .insert(user_id);
            if (ret == false) 
            {
                LOG_ERROR("数据插入失败!");
                return false;
            }
            else 
            {
                LOG_INFO("数据新增成功!");
                return true;
            }
        }

        //搜索
        std::vector<User> search(const std::string& key,const std::vector<std::string>& uid_list)
        {
            std::vector<User> res;
            //如果是nickname，就采用分词搜索
            Json::Value json_user = ESSearch(_client, "user")
            .append_should_match("phone.keyword", key)
            .append_should_match("user_id.keyword", key)
            .append_should_match("nickname", key) 
            .append_must_not_terms("user_id.keyword", uid_list)
            .search(); //append_must_not_terms 过滤条件
            if (json_user.isArray() == false) 
            {
                LOG_ERROR("结果不是数组类型");
                return res;
            } 
            else 
            {
                LOG_INFO("数据检索成功!");
            }

            int sz = json_user.size();
            // LOG_DEBUG("检索结果条目数量：{}", sz);
            for (int i = 0; i < sz; i++) 
            {
                User user;
                user.user_id(json_user[i]["_source"]["user_id"].asString());
                user.nickname(json_user[i]["_source"]["nickname"].asString());
                user.description(json_user[i]["_source"]["description"].asString());
                user.phone(json_user[i]["_source"]["phone"].asString());
                user.avatar_id(json_user[i]["_source"]["avatar_id"].asString());
                res.push_back(user);
            }
            return res;
        }

    private:
        std::shared_ptr<elasticlient::Client> _client;
    };
    class ESMessage
    {
    public:
        using ptr = std::shared_ptr<ESMessage>;
        ESMessage(std::shared_ptr<elasticlient::Client> client)
            :_client(client)
        {}

        //创建消息索引
        bool createIndex() 
        {
            bool ret = ESIndex(_client, "message")
                .append("user_id", "keyword", "standard", false)
                .append("message_id", "keyword", "standard", false)
                .append("create_time", "long", "standard", false)
                .append("chat_session_id", "keyword", "standard", true)
                .append("content")
                .create();
            if (ret == false) 
            {
                LOG_INFO("消息信息索引创建失败!");
                return false;
            }
            else
            {
                LOG_INFO("消息信息索引创建成功!");
                return true;
            }
        }

        //新增数据/修改数据
        bool appendData(const std::string& user_id,
            const std::string& message_id,
            const long& create_time,
            const std::string& chat_session_id,
            const std::string& content)
        {
            auto ret = ESInsert(_client, "message")
                .append("user_id", user_id)
                .append("message_id", message_id)
                .append("create_time",create_time)
                .append("chat_session_id", chat_session_id)
                .append("content", content)
                .insert(message_id);
            if (ret == false) 
            {
                LOG_ERROR("数据插入失败!");
                return false;
            }
            else 
            {
                LOG_INFO("数据新增成功!");
                return true;
            }
        }

        std::vector<Message> search(const std::string& key,const std::string& ssid)
        {
            std::vector<Message> res;
            //如果是nickname，就采用分词搜索
            Json::Value json_user = ESSearch(_client, "message")
            .append_must_term("chat_session_id.keyword",ssid)
            .append_must_match("content", key)
            .search(); //append_must_not_terms 过滤条件
            if (json_user.isArray() == false) 
            {
                LOG_ERROR("结果不是数组类型");
                return res;
            } 
            else 
            {
                LOG_INFO("数据检索成功!");
            }

            int sz = json_user.size();
            // LOG_DEBUG("检索结果条目数量：{}", sz);
            for (int i = 0; i < sz; i++) 
            {
                Message message;
                message.message_id(json_user[i]["_source"]["message_id"].asString());
                message.user_id(json_user[i]["_source"]["user_id"].asString());
                message.session_id(json_user[i]["_source"]["chat_session_id"].asString());
                message.content(json_user[i]["_source"]["content"].asString());

                boost::posix_time::ptime ctime(boost::posix_time::from_time_t(json_user[i]["_source"]["create_time"].asInt64()));

                message.create_time(ctime);
                res.push_back(message);
            }
            return res;
        }

        bool remove(const std::string &mid) 
        {
            bool ret = ESRemove(_client, "message").remove(mid);
            if (ret == false) 
            {
                LOG_ERROR("消息数据删除失败!");
                return false;
            }
            LOG_INFO("消息数据删除成功!");
            return true;
        }

    private:
        std::shared_ptr<elasticlient::Client> _client;
    };
}